package com;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 参考： {@link DefaultSingletonBeanRegistry}
 */
public class MyBeanRegistry {

    /**
     * 一级缓存
     * Cache of singleton objects: bean name to bean instance.
     */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /**
     * 二级缓存
     * Cache of singleton factories: bean name to ObjectFactory.
     */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    /**
     * 三级缓存
     * Cache of early singleton objects: bean name to bean instance.
     */
    private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);


    void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {

        synchronized (singletonObjects) {
            if (!singletonObjects.containsKey(beanName)) {
                // 加入第三级缓存
                singletonFactories.put(beanName, singletonFactory);
                earlySingletonObjects.remove(beanName);
            }
        }
    }

    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {

        // 查询一级缓存
        Object singletonObject = singletonObjects.get(beanName);

        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

            // 查询二级缓存
            singletonObject = earlySingletonObjects.get(beanName);

            if (singletonObject == null && allowEarlyReference) {

                synchronized (singletonObjects) {

                    singletonObject = singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = earlySingletonObjects.get(beanName);

                        if (singletonObject == null) {

                            // 查询第三级缓存
                            ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                singletonObject = singletonFactory.getObject();
                                singletonFactories.remove(beanName);
                                earlySingletonObjects.put(beanName, singletonObject);
                                return singletonObject;
                            }
                        }
                    }
                }
            }
        }
        return singletonObject;
    }

    private boolean isSingletonCurrentlyInCreation(String beanName) {
        return true;
    }

    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            //this.registeredSingletons.add(beanName);
        }
    }
}
